/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2023 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for Task_ADC */
osThreadId_t Task_ADCHandle;
const osThreadAttr_t Task_ADC_attributes = {
  .name = "Task_ADC",
  .stack_size = 256 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Task_Info */
osThreadId_t Task_InfoHandle;
const osThreadAttr_t Task_Info_attributes = {
  .name = "Task_Info",
  .stack_size = 256 * 4,
  .priority = (osPriority_t) osPriorityLow,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void AppTask_ADC(void *argument);
void AppTask_Info(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
	/* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
	/* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
	/* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
	/* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of Task_ADC */
  Task_ADCHandle = osThreadNew(AppTask_ADC, NULL, &Task_ADC_attributes);

  /* creation of Task_Info */
  Task_InfoHandle = osThreadNew(AppTask_Info, NULL, &Task_Info_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
	/* add threads, ... */
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
	/* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_AppTask_ADC */
/**
 * @brief  Function implementing the Task_ADC thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_AppTask_ADC */
void AppTask_ADC(void *argument)
{
  /* USER CODE BEGIN AppTask_ADC */
	lcd_show_str(10, 10 + 1 * 30, 24, "Task_ADC: ADC by polling", RED);

	TickType_t pxPreviousWakeTime = xTaskGetTickCount();
	/* Infinite loop */
	for (;;) {
		HAL_ADC_Start(&hadc1);
		if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
			uint32_t value = HAL_ADC_GetValue(&hadc1);
			uint32_t voltage = value * 3300 >> 12;


			lcd_show_str(10, 10 + 2 * 30, 24, "ADC Value(mv) =     ", RED);
			uint8_t temp_str[20];
			sprintf(temp_str, "ADC Value(mv) = %d", voltage);
			lcd_show_str(10, 10 + 2 * 30, 24, temp_str, RED);
		}
		vTaskDelayUntil(&pxPreviousWakeTime, pdMS_TO_TICKS(500));
	}
  /* USER CODE END AppTask_ADC */
}

/* USER CODE BEGIN Header_AppTask_Info */
/**
 * @brief Function implementing the Task_Info thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_AppTask_Info */
void AppTask_Info(void *argument)
{
  /* USER CODE BEGIN AppTask_Info */
	TaskHandle_t taskHandle = Task_ADCHandle;
	TaskStatus_t taskInfo;
	BaseType_t getFreeStackSpace = pdTRUE;
	eTaskState taskState = eInvalid;
	vTaskGetInfo(taskHandle, &taskInfo, getFreeStackSpace, taskState);

	taskENTER_CRITICAL();

	lcd_show_str(10, 10 + 4 * 30, 24, "Task_Info:", BLACK);
	lcd_show_str(10, 10 + 5 * 30, 24, "Get by vTaskGetInfo()", BLACK);

	uint8_t temp_str[40];
	sprintf(temp_str, "Task Name = %s", taskInfo.pcTaskName);
	lcd_show_str(10, 10 + 6 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Task Number = %d", taskInfo.xTaskNumber);
	lcd_show_str(10, 10 + 7 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Task State = %d", taskInfo.eCurrentState);
	lcd_show_str(10, 10 + 8 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Task Priority = %d", taskInfo.uxCurrentPriority);
	lcd_show_str(10, 10 + 9 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Stack High Water Mark = %d(Word)", taskInfo.usStackHighWaterMark);
	lcd_show_str(10, 10 + 10 * 30, 24, temp_str, RED);

	//--------

	lcd_show_str(10, 10 + 11 * 30, 24, "High Water Mark of tasks", BLACK);

	taskHandle = xTaskGetIdleTaskHandle();
	sprintf(temp_str, "Idle Task = %d", uxTaskGetStackHighWaterMark(taskHandle));
	lcd_show_str(10, 10 + 12 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Task_ADC = %d", uxTaskGetStackHighWaterMark(Task_ADCHandle));
	lcd_show_str(10, 10 + 13 * 30, 24, temp_str, RED);

	sprintf(temp_str, "Task_Info = %d", uxTaskGetStackHighWaterMark(Task_InfoHandle));
	lcd_show_str(10, 10 + 14 * 30, 24, temp_str, RED);

	//------------

	lcd_show_str(10, 10 + 16 * 30, 24, "Kernel Info", BLACK);

	sprintf(temp_str, "uxTaskGetNumberOfTasks() = %d", uxTaskGetNumberOfTasks());
	lcd_show_str(10, 10 + 17 * 30, 24, temp_str, RED);

	char pcWriteBuffer[300];
	vTaskList(pcWriteBuffer);
	lcd_show_str(10, 10 + 18 * 30, 24, pcWriteBuffer, RED);

	taskEXIT_CRITICAL();


	/* Infinite loop */
	for (;;) {
		for (uint8_t i = 0; i < 10; ++i) {
			LED1_Toggle();
			vTaskDelay(pdMS_TO_TICKS(300));
		}
		break;
	}

	lcd_show_str(10, 10 + 20 * 30, 24, "Task_Info is deleted", BLACK);
	vTaskDelete(NULL);
  /* USER CODE END AppTask_Info */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

